简介
V8 具有内存限制,所有的 JavaScript 对象都是通过堆来进行分配的,可以通过 process.memoryUsage()
来查看内存信息,其中 heapTotal 和 heapUsed 分别代表了已申请到的对内存和当前使用的量。如果当前代码已申请的堆空闲内存不够分配新的对象,将就申请堆内存,知道堆的大小超过 V8 的内存限制为止
为何采取 V8 内存限制:一次小的垃圾回收需要 50ms 以上,一次非增量式的垃圾回收甚至需要 1s 以上,这是垃圾回收引起的 JS 线程暂停执行的时间,应用的性能和响应时间都会大幅度下降
V8 的垃圾回收机制
采用 node –trace-gc xxx 命令行参数来查看内存垃圾回收日志,使用 –prof 可以得到 V8 执行时的性能分析数据,配合 tick-processor 工具查看统计信息
垃圾回收算法
基于分代式垃圾回收(解决不同的对象生命周期不同)
--max-old-space-size
指定老生代内存空间的最大值 +--max-new-space-size
指定新生代内存空间的最大值 = V8 堆的整体大小新生代的回收算法:Scavenge(base on Cheney)
核心思想:空间一分为二,从 From 空间 复制 到 To 空间,缺点是只能使用堆内存的一般,好处是以空间换取时间(块),适合新生代频繁的内存回收
对象晋升两个条件:是否经历过 Scavenge 回收,To空间的内存占用是否超过了比例(25%)
老生代的回收算法:Mark-Sweep & Mark-Compact
核心思想:标记 - 清楚 - 整理内存碎片
回收策略:延迟清理(lazy sweeping)和 增量式整理(incremental compaction)
为了降低全堆垃圾回收带来的线程停顿问题,采用增量标记来减少由于垃圾回收造成的停顿时间
高效使用内存
在正常的 JavaScript 执行中,无法立即回收的内存有必报和全局变量引用这两种情况,由于 V8 的内存限制,要十分小心此类变量是否无限制的增加,因为他会导致老生代的对象增多
内存指标
- 使用
process.memoryUsage()
查看 Node 进程的内存占用情况
1 | // outofmemory.js |
使用
os.totalmem()
和os.freemem()
查看 操作系统 的内存情况堆外内存:那些不是通过 V8 分配的内存 - Buffer 对象